/*************************************************************************************
 *
 *  Revolution Engine
 *  Copyright (C) 2009 Felipe Apablaza
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 ************************************************************************************/

#include <cstddef>
#include <RevEng/IObjCreator.hpp>

#include "ObjFactory.hpp"

#if defined(__REVENG_WINDOWS__)
#  include "ObjFactoryWin32.hpp"
#  define ObjFactoryImpl ObjFactoryWin32
#else
#  error Currently unsupported platform.
#endif

namespace RevEng
{
	//The object factory instance
	ObjFactory* ObjFactory::s_pInstance = NULL;

	//Return the current instance
	ObjFactory* ObjFactory::Instance()
	{
		if (ObjFactory::s_pInstance == NULL)
			ObjFactory::s_pInstance = dynamic_cast<ObjFactory*>(new ObjFactoryImpl);

		return ObjFactory::s_pInstance;
	}


	//Destroy the current instance.
	void ObjFactory::Delete()
	{
		if (ObjFactory::s_pInstance != NULL)
		{
			delete ObjFactory::s_pInstance;
			ObjFactory::s_pInstance = NULL;
		}
	}


	//Destroys all ObjCreators
	ObjFactory::~ObjFactory()
	{
		ObjCreatorReg::iterator RegIt;

		for(RegIt=m_mCreators.begin(); RegIt!=m_mCreators.end(); ++RegIt)
		{
			if (RegIt->second != NULL)
			{
				delete RegIt->second;
				RegIt->second = NULL;
			}
		}
	}


	//Register a new object creator
	void ObjFactory::RegObjCreator(IObjCreator* Creator)
	{
		if (Creator != NULL)
			m_mCreators[Creator->GetClassId()] = Creator;
	}


	//Instance a object wich implements the ClassId interface using 
	//the most adequate IObjCreator object.
	IObject* ObjFactory::New(Enum ClassId)
	{
		ObjCreatorReg::iterator RegIt;
		
		RegIt = m_mCreators.find(ClassId);

		if ( RegIt != m_mCreators.end() )
			return RegIt->second->New();
		else
			return NULL;
	}

	const std::type_info& ObjFactory::GetTypeInfo( Enum ClassId ) const
	{
		ObjCreatorReg::const_iterator RegIt;
		
		RegIt = m_mCreators.find(ClassId);

		if ( RegIt != m_mCreators.end() )
			return RegIt->second->GetTypeInfo();
		else
			throw std::bad_exception("Unregistered ClassId");
	}
}
